﻿using GameToolkit.BehaviourTree;
using UnityEditor.Experimental.GraphView;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using Devil;

namespace GameToolkit.Editor
{
    using CompositeInfo = BehaviourTreeLib.CompositeInfo;

    //public partial class BehaviourTreeGraph
    //{

    internal abstract class TreeGraphNode : Node, INodeWithComposite
    {
        Composite mComposite;
        protected CompositeInfo mCompositeInfo;
        public virtual Composite composite
        {
            get
            {
                return mComposite;
            }
            set
            {
                if (mComposite != value)
                {
                    mCompositeInfo = BehaviourTreeLib.Instance.GetCompositeInfo(value);
                    mComposite = value;
                    viewDataKey = value == null ? null : value._guid;
                    var icon = mCompositeInfo?.Icon;
                    if (icon != null)
                        mIcon.style.backgroundImage = icon;
                    Validate();
                }
            }
        }
        public Vector2 position => GetPosition().position;
        public CompositeInfo compositeInfo => mCompositeInfo;
        protected Label mDescript;
        protected VisualElement mContentContainer;
        protected VisualElement mIcon;
        public VisualElement btContainer => mContentContainer;
        public virtual bool IsDecoratorEditable => !EditorApplication.isPlayingOrWillChangePlaymode;

        public int temporaryPortId { get; set; }

        public TreeGraphNode(CompositeInfo composite, Composite asset) : base()
        {
            mCompositeInfo = composite;
            mComposite = asset;

            viewDataKey = asset._guid;

            var icon = new VisualElement();
            icon.name = "icon";
            icon.AddToClassList("node-icon");
            titleContainer.Insert(0, icon);
            var icontex = composite.Icon;
            if (icontex != null)
                icon.style.backgroundImage = icontex;
            mIcon = icon;

            mContentContainer = new VisualElement();
            mContentContainer.name = "node-container";
            mContentContainer.AddToClassList("node-contents");
            mainContainer.Add(mContentContainer);

            var desc = new Label();
            desc.AddToClassList("node-descript");
            btContainer.Add(desc);
            mDescript = desc;

            SetPosition(new Rect(mComposite.m_Position, Vector2.zero));

            capabilities &= ~Capabilities.Collapsible;
            capabilities |= Capabilities.Groupable;

            title = composite.Title;
            mDescript.text = BehaviourTreeLib.Instance.GetDescription(mComposite);
        }

        public virtual void Validate()
        {
            if (mCompositeInfo != null)
                title = mCompositeInfo.Title;
            if (mComposite != null)
            {
                var desc = BehaviourTreeLib.Instance.GetDescription(mComposite);
                mDescript.text = desc;
            }
        }

        internal virtual void NotifyRemoved() { }
        public abstract int GetInputPortId(Edge edge);
        public abstract Port GetInputPort(int portId);
        public abstract int GetOutputPortId(Edge edge);
        public abstract Port GetOutputPort(int portId);
        public abstract void SaveCompositeConnections(MinHeap<INodeWithComposite> nodeBuffer);
        public abstract void LoadCompositeConnections(BehaviourTreeGraph.GraphEdgeLoader edgeLoader);
        public abstract void AutoConnectOnCreate(BehaviourTreeGraph graph, Port port);
        public abstract bool IsCompatiblePort(Port port);
    }
    //}
}
